#region File Description
//-----------------------------------------------------------------------------
// GameplayScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Tetris_AntiGravity;
using Lidgren.Network;
using Tetris_AntiGravity.network;
#endregion

namespace GameStateManagement
{
    /// <summary>
    /// This screen implements the actual game logic. It is just a
    /// placeholder to get the idea across: you'll probably want to
    /// put some more interesting gameplay in here!
    /// </summary>
    class GameplayScreen : GameScreen
    {
        #region Fields

        ContentManager content;
        SpriteFont gameFont;

        Vector2 playerPosition = new Vector2(100, 100);
        Vector2 enemyPosition = new Vector2(100, 100);

        Random random = new Random();

        float pauseAlpha;

        #endregion

        #region variablesJuego

        //variables que manejan los jugadores
        private Jugador jugador1;
        private Jugador jugador2;
        //Variable para el manejo del frameRate
        int incrementoTiempo = 0;
        SpriteFont scoreFont;
        public Texture2D texturaFondo;
        public Texture2D AssetLampara1;
        public Texture2D AssetLampara2; 
        private Texture2D youWinSprite;
        private Texture2D youLoseSprite;

        NetClient cliente;
        

        #endregion

        #region Initialization


        /// <summary>
        /// Constructor.
        /// </summary>
        public GameplayScreen()
        {
            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);
        }

        public GameplayScreen(NetClient cliente)
        {
            this.cliente = cliente;
        }


        /// <summary>
        /// Load graphics content for the game.
        /// </summary>
        public override void LoadContent()
        {
            if (content == null)
                content = new ContentManager(ScreenManager.Game.Services, "Content");

            gameFont = content.Load<SpriteFont>(@"fuentes\gamefont");


            youWinSprite = ScreenManager.Game.Content.Load<Texture2D>(@"assets/youwin");
            youLoseSprite = ScreenManager.Game.Content.Load<Texture2D>(@"assets/youlose");


            jugador1 = new Jugador(new Vector2(50, 90), ScreenManager.Game);
            JugadorNetwork jugNetwork = new JugadorNetwork(jugador1);
            
            NetOutgoingMessage outmsg = cliente.CreateMessage();
            
            outmsg.Write((byte)TipoPaquete.INICIALIZACION);
            //outmsg.WriteAllFields(jugNetwork);
            jugNetwork.escribirPaquete(outmsg);

            cliente.SendMessage(outmsg, NetDeliveryMethod.ReliableOrdered);

            bool inicializar = false;
            NetIncomingMessage msg;
            while (!inicializar)
            {
                msg = cliente.ReadMessage();
                if (msg != null)
                {
                    if (msg.MessageType == NetIncomingMessageType.Data)
                    {
                        TipoPaquete tipopaq =(TipoPaquete) msg.ReadByte();
                        JugadorNetwork jn = new JugadorNetwork();
                        
                        if (tipopaq == TipoPaquete.INICIALIZACION)
                        {
                            //msg.ReadAllFields(jn);
                            jn.leerPaquete(msg);
                            inicializar = true;
                            jugador2 = new Jugador(new Vector2(835, 90), ScreenManager.Game);

                            jugador2.bombas = jn.bombas;
                            jugador2.figuraActual.tipo=(TipoFigura)jn.figuraActual;
                            jugador2.figuraActual.posicion.X = jn.posX;
                            jugador2.figuraActual.posicion.Y = jn.posY;
                            jugador2.figuraSiguiente.tipo = (TipoFigura)jn.figuraProxima;
                            jugador2.sumaLineas = jn.lineas;
                            jugador2.tornado = jn.tornados;


                        }
                        
                    }
                }
            }
            
            scoreFont = content.Load<SpriteFont>(@"fuentes\letra");

            this.texturaFondo = content.Load<Texture2D>(@"fondos/fondo");
            this.AssetLampara1 = content.Load<Texture2D>(@"assets/lampara");
            this.AssetLampara2 = content.Load<Texture2D>(@"assets/lampara");

            // A real game would probably have more content than this sample, so
            // it would take longer to load. We simulate that by delaying for a
            // while, giving you a chance to admire the beautiful loading screen.
            Thread.Sleep(1000);

            // once the load has finished, we use ResetElapsedTime to tell the game's
            // timing mechanism that we have just finished a very long frame, and that
            // it should not try to catch up.
            ScreenManager.Game.ResetElapsedTime();
        }


        /// <summary>
        /// Unload graphics content used by the game.
        /// </summary>
        public override void UnloadContent()
        {
            content.Unload();
        }


        #endregion

        #region Update and Draw


        /// <summary>
        /// Updates the state of the game. This method checks the GameScreen.IsActive
        /// property, so the game will stop updating when the pause menu is active,
        /// or if you tab away to a different application.
        /// </summary>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {
            base.Update(gameTime, otherScreenHasFocus, false);

            // Gradually fade in or out depending on whether we are covered by the pause screen.
            if (coveredByOtherScreen)
                pauseAlpha = Math.Min(pauseAlpha + 1f / 32, 1);
            else
                pauseAlpha = Math.Max(pauseAlpha - 1f / 32, 0);

            //if (IsActive)
            //{


            NetIncomingMessage msg;


            while ((msg = cliente.ReadMessage()) != null)
            {
                if (msg.MessageType == NetIncomingMessageType.Data)
                {
                    TipoPaquete tipoPac = (TipoPaquete)msg.ReadByte();

                    if (tipoPac == TipoPaquete.ACTUALIZAR)
                    {
                        JugadorNetwork jn2 = new JugadorNetwork();
                        jn2.leerPaquete(msg);

                        if (jn2.id != cliente.UniqueIdentifier)
                        {
                            jugador2.bombas = jn2.bombas;
                            jugador2.figuraActual.tipo = (TipoFigura)jn2.figuraActual;
                            jugador2.figuraActual.posicion.X = jn2.posX;
                            jugador2.figuraActual.posicion.Y = jn2.posY;
                            jugador2.figuraSiguiente.tipo = (TipoFigura)jn2.figuraProxima;
                            jugador2.sumaLineas = jn2.lineas;
                            jugador2.figuraActual.rotacion = jn2.rotacion;
                            jugador2.tornado = jn2.tornados;
                            jugador2._tablero.tablero = jn2.getTableroJugador();

                            if (jn2.perdio == 1)
                                jugador2._tablero.tableroTerminado = true;
                            else

                                jugador2._tablero.tableroTerminado = false;
                        }
                    }

                    if (tipoPac == TipoPaquete.MOVIMIENTO)
                    {
                        TipoAtaque ataque = (TipoAtaque)msg.ReadByte();

                        switch (ataque)
                        {
                            case TipoAtaque.GRANADA:
                                jugador1.lanzarGranada();
                                break;
                            case TipoAtaque.SUMAR:
                                jugador1.agregarLinea();
                                break;
                            case TipoAtaque.TORNADO:
                                jugador1.lanzarTornado();
                                break;
                        }
                    }

                    if (tipoPac == TipoPaquete.FINALIZAR)
                    {
                        JugadorNetwork jn2 = new JugadorNetwork();
                        jn2.leerPaquete(msg);

                        if (jn2.id != cliente.UniqueIdentifier)
                        {
                            jugador2.bombas = jn2.bombas;
                            jugador2.figuraActual.tipo = (TipoFigura)jn2.figuraActual;
                            jugador2.figuraActual.posicion.X = jn2.posX;
                            jugador2.figuraActual.posicion.Y = jn2.posY;
                            jugador2.figuraSiguiente.tipo = (TipoFigura)jn2.figuraProxima;
                            jugador2.sumaLineas = jn2.lineas;
                            jugador2.tornado = jn2.tornados;
                            if (jn2.perdio == 1)
                                jugador2._tablero.tableroTerminado = true;
                            else
                                jugador2._tablero.tableroTerminado = false;
                            jugador2._tablero.tablero = jn2.getTableroJugador();
                        }

                    }

                }
            }




                if (!jugador1.perdio && !jugador2.perdio)
                {
                    incrementoTiempo += gameTime.ElapsedGameTime.Milliseconds;
                    KeyboardState teclado = Keyboard.GetState();

                    if (incrementoTiempo > 1000 / 5)
                    {
                        if (teclado.IsKeyDown(Keys.Down))
                            jugador1.rotarFicha();
                            
                        if (teclado.IsKeyDown(Keys.Right))
                            jugador1.moverDerecha();

                        if (teclado.IsKeyDown(Keys.Left))
                            jugador1.moverIzquierda();

                        if (teclado.IsKeyDown(Keys.Up))
                            jugador1.subir();

                        if (teclado.IsKeyDown(Keys.PageUp))
                        {
                            if (jugador1.sumaLineas > 0)
                            {
                                NetOutgoingMessage msgSalida = cliente.CreateMessage();
                                msgSalida.Write((byte)TipoPaquete.MOVIMIENTO);
                                msgSalida.Write((byte)TipoAtaque.SUMAR);
                                cliente.SendMessage(msgSalida, NetDeliveryMethod.ReliableOrdered);
                                jugador1.sumaLineas--;
                            }
                        }

                        

                        if (teclado.IsKeyDown(Keys.PageDown))
                        {
                            if (jugador2.sumaLineas > 0)
                            {
                                jugador2.eliminarLinea();
                                jugador2.sumaLineas--;
                            }
                        }

                        

                        if (teclado.IsKeyDown(Keys.Home))
                        {

                            if (jugador1.tornado > 0)
                            {
                                NetOutgoingMessage msgSalida = cliente.CreateMessage();
                                msgSalida.Write((byte)TipoPaquete.MOVIMIENTO);
                                msgSalida.Write((byte)TipoAtaque.TORNADO);
                                cliente.SendMessage(msgSalida, NetDeliveryMethod.ReliableOrdered);

                                jugador1.lanzarTornadoOponente();
                                jugador1.tornado--;
                            }
                            
                            
                        }


                        if (teclado.IsKeyDown(Keys.End))
                        {
                            if (jugador2.bombas > 0)
                            {
                                NetOutgoingMessage msgSalida = cliente.CreateMessage();
                                msgSalida.Write((byte)TipoPaquete.MOVIMIENTO);
                                msgSalida.Write((byte)TipoAtaque.GRANADA);
                                cliente.SendMessage(msgSalida, NetDeliveryMethod.ReliableOrdered);
                                jugador1.lanzarGranadaOponente();
                                jugador1.bombas--;
                            }
                            
                            
                        }

                        if (teclado.IsKeyDown(Keys.H))
                        {
                            if (jugador1.bombas > 0)
                            {
                                jugador2.lanzarGranada();
                                jugador1.bombas--;
                            }
                        }


                        incrementoTiempo = 0;
                    }

                    jugador1.update(gameTime);
                    //jugador2.update(gameTime);

                    NetOutgoingMessage outmsg = cliente.CreateMessage();
                    outmsg.Write((byte)TipoPaquete.ACTUALIZAR);
                    JugadorNetwork jn = new JugadorNetwork(jugador1);
                    jn.id = cliente.UniqueIdentifier;
                    jn.escribirPaquete(outmsg);
                    
                    cliente.SendMessage(outmsg, NetDeliveryMethod.ReliableOrdered);

                    

                //}

            }
        }


        /// <summary>
        /// Lets the game respond to player input. Unlike the Update method,
        /// this will only be called when the gameplay screen is active.
        /// </summary>
        public override void HandleInput(InputState input)
        {
            if (input == null)
                throw new ArgumentNullException("input");

            // Look up inputs for the active player profile.
            int playerIndex = (int)ControllingPlayer.Value;

            KeyboardState keyboardState = input.CurrentKeyboardStates[playerIndex];
            GamePadState gamePadState = input.CurrentGamePadStates[playerIndex];

            // The game pauses either if the user presses the pause button, or if
            // they unplug the active gamepad. This requires us to keep track of
            // whether a gamepad was ever plugged in, because we don't want to pause
            // on PC if they are playing with a keyboard and have no gamepad at all!
            bool gamePadDisconnected = !gamePadState.IsConnected &&
                                       input.GamePadWasConnected[playerIndex];

            if (input.IsPauseGame(ControllingPlayer) || gamePadDisconnected)
            {
                ScreenManager.AddScreen(new PauseMenuScreen(), ControllingPlayer);
            }
            else
            {
                // Otherwise move the player position.
                Vector2 movement = Vector2.Zero;

                if (keyboardState.IsKeyDown(Keys.Left))
                    movement.X--;

                if (keyboardState.IsKeyDown(Keys.Right))
                    movement.X++;

                if (keyboardState.IsKeyDown(Keys.Up))
                    movement.Y--;

                if (keyboardState.IsKeyDown(Keys.Down))
                    movement.Y++;

                Vector2 thumbstick = gamePadState.ThumbSticks.Left;

                movement.X += thumbstick.X;
                movement.Y -= thumbstick.Y;

                if (movement.Length() > 1)
                    movement.Normalize();

                playerPosition += movement * 2;
            }
        }


        /// <summary>
        /// Draws the gameplay screen.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            // This game has a blue background. Why? Because!
            ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
                                               Color.CornflowerBlue, 0, 0);

            // Our player and enemy are both actually just text strings.
            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;

            spriteBatch.Begin();
            
            spriteBatch.Draw(texturaFondo, new Vector2(0, 0), Color.White);
            spriteBatch.Draw(AssetLampara1, new Vector2(7, 0), Color.White);
            spriteBatch.Draw(AssetLampara2, new Vector2(792, 0), Color.White);

            jugador2.Draw(gameTime, spriteBatch, ScreenManager.GraphicsDevice);
            jugador1.Draw(gameTime, spriteBatch, ScreenManager.GraphicsDevice);
            
            spriteBatch.DrawString(scoreFont, "" + jugador1.puntaje, new Vector2(190, 678), Color.Black, 0, Vector2.Zero, 1.5f, SpriteEffects.None, 1);
            spriteBatch.DrawString(scoreFont, "" + jugador2.puntaje, new Vector2(980, 678), Color.Black, 0, Vector2.Zero, 1.5f, SpriteEffects.None, 1);
            spriteBatch.DrawString(scoreFont, "" + jugador1.bombas, new Vector2(535, 323), Color.Black, 0, Vector2.Zero, 1.5f, SpriteEffects.None, 1);
            spriteBatch.DrawString(scoreFont, "" + jugador2.bombas, new Vector2(696, 323), Color.Black, 0, Vector2.Zero, 1.5f, SpriteEffects.None, 1);
            spriteBatch.DrawString(scoreFont, "" + jugador1.tornado, new Vector2(535, 435), Color.Black, 0, Vector2.Zero, 1.5f, SpriteEffects.None, 1);
            spriteBatch.DrawString(scoreFont, "" + jugador2.tornado, new Vector2(696, 435), Color.Black, 0, Vector2.Zero, 1.5f, SpriteEffects.None, 1);
            spriteBatch.DrawString(scoreFont, "" + jugador1.sumaLineas, new Vector2(535, 548), Color.Black, 0, Vector2.Zero, 1.5f, SpriteEffects.None, 1);
            //spriteBatch.DrawString(scoreFont, "" + incrementoTiempo, new Vector2(515, 543), Color.Black, 0, Vector2.Zero, 1.5f, SpriteEffects.None, 1);
            spriteBatch.DrawString(scoreFont, "" + jugador2.sumaLineas, new Vector2(696, 548), Color.Black, 0, Vector2.Zero, 1.5f, SpriteEffects.None, 1);

            if (jugador1.perdio)
            {
                spriteBatch.Draw(youLoseSprite, new Vector2(400, 300), Color.White);
            }

            if (jugador2.perdio)
            {
                spriteBatch.Draw(youWinSprite, new Vector2(400, 300), Color.White);
            }


            spriteBatch.End();

            // If the game is transitioning on or off, fade it out to black.
            if (TransitionPosition > 0 || pauseAlpha > 0)
            {
                float alpha = MathHelper.Lerp(1f - TransitionAlpha, 1f, pauseAlpha / 2);

                ScreenManager.FadeBackBufferToBlack(alpha);
            }
        }

        public void crearPaquete(NetOutgoingMessage msg, Jugador jugador, TipoPaquete tipo)
        {
            JugadorNetwork jugNetwork = new JugadorNetwork(jugador);
            msg.Write((byte)tipo);
            msg.Write((byte)jugNetwork.bombas);
            msg.Write((byte)jugNetwork.figuraActual);
            msg.Write((byte)jugNetwork.figuraProxima);
            msg.Write((byte)jugNetwork.lineas);
            msg.Write((byte)jugNetwork.posX);
            msg.Write((byte)jugNetwork.posY);
            msg.Write((byte)jugNetwork.rotacion);
            msg.Write((byte)jugNetwork.tornados);
            
        }

        public JugadorNetwork leerPaqueteJugador(NetIncomingMessage mensaje)
        {
            JugadorNetwork jugN = new JugadorNetwork();
            jugN.bombas = mensaje.ReadByte();
            jugN.figuraActual = mensaje.ReadByte();
            jugN.figuraProxima = mensaje.ReadByte();
            jugN.lineas = mensaje.ReadByte();
            jugN.posX = mensaje.ReadByte();
            jugN.posY = mensaje.ReadByte();
            jugN.rotacion = mensaje.ReadByte();
            jugN.tornados = mensaje.ReadByte();

            return jugN;
        }




        #endregion
    }
}
